﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using Microsoft.Win32;


namespace BildUppladdaren
{
    public partial class Bilduppladdaren : Form
    {
        public Bilduppladdaren()
        {
            InitializeComponent();

            //Set version label
            lblversion.Text = "Version " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();

            this.GetAlbums();
        }


        private void GetAlbums()
        {

            this.comboBoxAlbums.Items.Clear();

            osdk.kumlacs.se.Service1 webService = new BildUppladdaren.osdk.kumlacs.se.Service1();

            object[] albums = webService.AlbumGetAll();


            foreach (string albumName in albums)
            {
                this.comboBoxAlbums.Items.Add(albumName);
            }

        }

        private void UserControl1_DragDrop(object sender, DragEventArgs e)
        {

            //Start new thread for each file to load. This will speed things up a bit.
            System.Collections.ArrayList threads = new System.Collections.ArrayList();

            //Loop all files
            foreach (string fileListItem in (e.Data.GetData("FileDrop") as string[]))
            {

                //Add files to grid
                System.IO.FileInfo fi = new System.IO.FileInfo(fileListItem);


                if (fi.Extension.ToLower() == ".jpg")
                {
                    //Create worker to read file
                    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(ReadAndLoadImageFromDisc), fi);
                }
            }
        }

        private void DoPopulateGridWithImage(System.IO.FileInfo fi, Image myImage)
        {

            if (this.dgFiles.InvokeRequired)
            {

                this.Invoke(new PopulateGridWithImageCallBack(DoPopulateGridWithImage), new object[] { fi, myImage });
            }
            else
            {
                this.PopulateGridWithImage(fi, myImage);

                UpdateStatusLabel();
            }
        }

        private void UpdateStatusLabel()
        {
            //Update progressbar
            this.lblStatus.Text = string.Format("{0} av {1}", new object[] { 0, this.dgFiles.Rows.Count.ToString() });
        }
        delegate void PopulateGridWithImageCallBack(System.IO.FileInfo fi, Image myImage);

        private void PopulateGridWithImage(System.IO.FileInfo fi, Image myImage)
        {
            myImage = myImage.GetThumbnailImage(75, 75, null, IntPtr.Zero);

            int rowid = dgFiles.Rows.Add(new object[] { fi.FullName, (fi.Length / 1024) + "Kb", myImage, false });

            dgFiles.Rows[rowid].Height = myImage.Height;

            dgFiles.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

            this.Update();

        }

        private void ReadAndLoadImageFromDisc(object fileInfo)
        {
            Image myImage = Image.FromFile(((System.IO.FileInfo)fileInfo).FullName);

            DoPopulateGridWithImage((System.IO.FileInfo)fileInfo, myImage);
        }

        private void UserControl1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("FileDrop"))
                e.Effect = DragDropEffects.Copy;
            else
                e.Effect = DragDropEffects.None;

        }

        enum AnchorPosition
        {
            Top,
            Center,
            Bottom,
            Left,
            Right
        }

        static Image Crop(Image imgPhoto, int Width, int Height, AnchorPosition Anchor)
        {
            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)Width / (float)sourceWidth);
            nPercentH = ((float)Height / (float)sourceHeight);

            if (nPercentH < nPercentW)
            {
                nPercent = nPercentW;
                switch (Anchor)
                {
                    case AnchorPosition.Top:
                        destY = 0;
                        break;
                    case AnchorPosition.Bottom:
                        destY = (int)
                            (Height - (sourceHeight * nPercent));
                        break;
                    default:
                        destY = (int)
                            ((Height - (sourceHeight * nPercent)) / 2);
                        break;
                }
            }
            else
            {
                nPercent = nPercentH;
                switch (Anchor)
                {
                    case AnchorPosition.Left:
                        destX = 0;
                        break;
                    case AnchorPosition.Right:
                        destX = (int)
                          (Width - (sourceWidth * nPercent));
                        break;
                    default:
                        destX = (int)
                          ((Width - (sourceWidth * nPercent)) / 2);
                        break;
                }
            }

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap bmPhoto = new Bitmap(Width,
                    Height, PixelFormat.Format24bppRgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                    imgPhoto.VerticalResolution);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.InterpolationMode =
                    InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, destWidth, destHeight),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();
            return bmPhoto;
        }

        static Image FixedSize(Image imgPhoto, int Width, int Height)
        {
            int sourceWidth = imgPhoto.Width;
            int sourceHeight = imgPhoto.Height;
            int sourceX = 0;
            int sourceY = 0;
            int destX = 0;
            int destY = 0;

            float nPercent = 0;
            float nPercentW = 0;
            float nPercentH = 0;

            nPercentW = ((float)Width / (float)sourceWidth);
            nPercentH = ((float)Height / (float)sourceHeight);
            if (nPercentH < nPercentW)
            {
                nPercent = nPercentH;
                destX = System.Convert.ToInt16((Width -
                              (sourceWidth * nPercent)) / 2);
            }
            else
            {
                nPercent = nPercentW;
                destY = System.Convert.ToInt16((Height -
                              (sourceHeight * nPercent)) / 2);
            }

            int destWidth = (int)(sourceWidth * nPercent);
            int destHeight = (int)(sourceHeight * nPercent);

            Bitmap bmPhoto = new Bitmap(Width, Height,
                              PixelFormat.Format24bppRgb);
            bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                             imgPhoto.VerticalResolution);

            Graphics grPhoto = Graphics.FromImage(bmPhoto);
            grPhoto.Clear(Color.Red);
            grPhoto.InterpolationMode =
                    InterpolationMode.HighQualityBicubic;

            grPhoto.DrawImage(imgPhoto,
                new Rectangle(destX, destY, destWidth, destHeight),
                new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
                GraphicsUnit.Pixel);

            grPhoto.Dispose();
            return bmPhoto;
        }

        static Image MaxSize(Image imgPhoto, double maxHeight, double maxWidth)
        {

            // Declare variable for the conversion
            float ratio;
            
            // Create variable to hold the image
            System.Drawing.Image thisImage = imgPhoto;

            // Get height and width of current image
            int width = (int)thisImage.Width;
            int height = (int)thisImage.Height;

            // Ratio and conversion for new size
            if (width > maxWidth)
            {
                ratio = (float)width / (float)maxWidth;
                width = (int)(width / ratio);
                height = (int)(height / ratio);
            }

            // Ratio and conversion for new size
            if (height > maxHeight)
            {
                ratio = (float)height / (float)maxHeight;
                height = (int)(height / ratio);
                width = (int)(width / ratio);
            }

            // Create "blank" image for drawing new image
            Bitmap outImage = new Bitmap(width, height);
            Graphics outGraphics = Graphics.FromImage(outImage);
            SolidBrush sb = new SolidBrush(System.Drawing.Color.White);
            
            outGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
            outGraphics.SmoothingMode = SmoothingMode.HighQuality;
            outGraphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            outGraphics.CompositingQuality = CompositingQuality.HighQuality;

            //Copy image MetaData
            foreach (System.Drawing.Imaging.PropertyItem property in imgPhoto.PropertyItems)
            {
                outImage.SetPropertyItem(property);
            }

            // Fill "blank" with new sized image
            outGraphics.FillRectangle(sb, 0, 0, outImage.Width, outImage.Height);
            outGraphics.DrawImage(thisImage, 0, 0, outImage.Width, outImage.Height);
            sb.Dispose();
            outGraphics.Dispose();
            thisImage.Dispose();

            return outImage;

        }

        private void dgFiles_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            this.CheckUncheck((DataGridView)sender, e);
        }

        /// <summary>
        /// Check or uncheck checkbox in grid
        /// </summary>
        /// <param name="grid"></param>
        /// <param name="e"></param>
        private void CheckUncheck(DataGridView grid, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex != -1 && e.RowIndex != -1 && grid.Rows[e.RowIndex].Cells[e.ColumnIndex] is System.Windows.Forms.DataGridViewCheckBoxCell)
            {

                if ((bool)((System.Windows.Forms.DataGridViewCheckBoxCell)grid.Rows[e.RowIndex].Cells[e.ColumnIndex]).Value)
                {
                    ((System.Windows.Forms.DataGridViewCheckBoxCell)grid.Rows[e.RowIndex].Cells[e.ColumnIndex]).Value = false;
                }
                else
                {
                    ((System.Windows.Forms.DataGridViewCheckBoxCell)grid.Rows[e.RowIndex].Cells[e.ColumnIndex]).Value = true;
                }

            }
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            foreach (DataGridViewRow row in dgFiles.Rows)
            {
                if ((bool)row.Cells["Tabort"].Value)
                {
                    dgFiles.Rows.Remove(row);
                    //Update status lable
                    this.UpdateStatusLabel();
                }
            }
        }

        private void btnUpload_Click(object sender, EventArgs e)
        {
            try
            {
                if (this.comboBoxAlbums.Text== "")
                {
                    MessageBox.Show("Du måste skriva i ett namn.", "Har du inget namn?", MessageBoxButtons.OK);
                    return;
                }

                if (this.txtDescription.Text == "")
                {
                    MessageBox.Show("Du måste skriva en kort beskrivning.", "Inget roligt att skriva?", MessageBoxButtons.OK);
                    return;
                }

                //Connect to webservice
                osdk.kumlacs.se.Service1 webService = new osdk.kumlacs.se.Service1();

                //Check if album already exits, if so ask user to continue
                if (webService.AlbumExits(this.comboBoxAlbums.Text))
                {
                    DialogResult result = MessageBox.Show("Albumet finns redan, vill du verkligen fortsätta ladda upp bilder i samma album?", "Albumet finns redan!", MessageBoxButtons.YesNo);

                    if (result == DialogResult.No)
                    {
                        return;
                    }
                }

                //Change mouse
                Cursor.Current = Cursors.WaitCursor;
                this.btnUpload.Enabled = false;
                this.btnRemove.Enabled = false;

                //Reset progressbar and set init valus
                progressBar1.Value = 0;
                int fileNo = dgFiles.Rows.Count;

                if (fileNo > 0)
                {


                    int Increment = (100 / fileNo);
                    int fileNr = 0;



                    //Loop all files
                    foreach (DataGridViewRow row in dgFiles.Rows)
                    {
                        //Increment progressbar
                        progressBar1.Increment(Increment);
                        fileNr = fileNr + 1;
                        lblStatus.Text = string.Format("{0} av {1}", new object[] { fileNr, fileNo });

                        this.Update();

                        //Create ftp command
                        System.IO.FileInfo fi = new System.IO.FileInfo(row.Cells["Filnamn"].Value.ToString());

                        //Crop/resize file
                        Image myImage = Image.FromFile(fi.FullName);
                        //myImage = Crop(myImage, 800, 600,AnchorPosition.Center);
                        myImage = MaxSize(myImage, 800  , 800);

                        System.IO.MemoryStream stream = new System.IO.MemoryStream();

                        //Set quality
                        ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
                        EncoderParameters encoderParameters;
                        encoderParameters = new EncoderParameters(1);
                        encoderParameters.Param[0] = new EncoderParameter( System.Drawing.Imaging.Encoder.Quality, 100L);
                        myImage.Save(stream, info[1], encoderParameters);

                        myImage.Dispose();

                        //Create array
                        byte[] b = stream.ToArray();

                        //Upload file
                        webService.Upload(b, fi.Name, this.comboBoxAlbums.Text);

                    }
                }
                //Set completed
                progressBar1.Value = 100;

                //Remove item from grid
                dgFiles.Rows.Clear();

                //Change mouse
                Cursor.Current = Cursors.Default;
                this.btnUpload.Enabled = true;
                this.btnRemove.Enabled = true;


                //Get IP's
                string ip = "";
                try
                {
                    for (int i = 0; i < System.Net.Dns.GetHostEntry(System.Environment.MachineName).AddressList.Length; i++)
                    {
                        ip = ip + System.Net.Dns.GetHostEntry(System.Environment.MachineName).AddressList[i].ToString() + ";";
                    }

                }
                catch (Exception)
                {
                    ip = "Ingen ip hittades";
                }

                //Send email notification
                string mailResult = webService.SendMail(this.comboBoxAlbums.Text, this.txtDescription.Text, System.Environment.MachineName, ip);

                if (mailResult != string.Empty)
                {
                    lblStatus.Text = "Ett fel uppstod: " + mailResult;
                }

                MessageBox.Show("Bilderna är nu uppladdade");

            }
            catch (Exception ex)
            {
                lblStatus.Text = "Ett fel uppstod: " + ex.Message;
                progressBar1.Value = 100;
            }
            finally {

                //Update albumlist
                this.GetAlbums();
            }

        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            this.txtDescription.Text = "";
        }
    }
}
